package com.google.code.jbauble.mvc.support;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ViewResourceCache {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	private static ViewResourceCache cache;
	
	private Map<String, ViewResourceContext> viewCacheMap = null;
	private String viewPath = null;
	private long overtime = 0;
	private String encoding = null;
	
	private ViewResourceCache(String viewPath, long overtime, String encoding) {
		viewCacheMap = new HashMap();
		this.viewPath = viewPath;
		this.overtime = overtime;
		this.encoding = encoding;
	}
	
	public static ViewResourceCache init(String viewPath, long overtime, String encoding) {
		cache = new ViewResourceCache(viewPath, overtime, encoding);
		return cache;
	}
	
	public static ViewResourceCache getInstance() {
		return cache;
	}

	public ViewResourceContext getView(String name) {
		Date d = new Date();
		ViewResourceContext c = viewCacheMap.get(name);
		if (c == null)
			return null;
		if (c.getOvertime() == 0 || c.getOvertime() < d.getTime())
			viewCacheMap.remove(name);
		return c;
	}
	
	public void setView(String name, ViewResourceContext c) {
		Date d = new Date();
		c.setOvertime(overtime > 0 ? d.getTime() + overtime : 0);
		viewCacheMap.put(name, c);
	}
	
	public boolean containsView(String name) {
		return viewCacheMap.containsKey(name);
	}

	public ViewResourceContext loadView(String name) throws IOException {
		ViewResourceContext c = getView(name);
		if (c == null || c.getViewContent() == null) {
			c = loadViewFromFile(name);
		}
		
		return c;
	}
	
	public ViewResourceContext loadViewFromFile(String name) throws IOException {
		ViewResourceContext r = loadViewResourceContext(name);
		setView(name, r);
		return r;
	}
	
	public ViewResourceContext loadViewResourceContext(String name) throws IOException {
		String file = UrlHelper.mergeUrl(viewPath, name);
		File f = new File(file);
		if (!f.exists())
			throw new FileNotFoundException(file);
		
		ViewResourceContext r = null;
		FileInputStream stream = new FileInputStream(f);
		byte[] buff;
		try {
			buff = new byte[stream.available()];
			stream.read(buff);
		
			r = new ViewResourceContext();
			r.setViewContent(new String(buff, encoding));
			r.setResourceName(name);
			r.setOvertime(overtime);
			return r;
		} catch (IOException e) {
			log.error("Read file error." + name, e);
			throw e;
		}
		finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					log.error("Close file stream error." + name, e);
				}
			}
		}
	}
}
